package com.qd.panda.service.park;

import cn.hutool.core.math.Money;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.db.BaseService;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.cdqidi.util.ServletUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.carpark.CarParkGasStationDTO;
import com.qd.common.panda.domain.entity.carpark.CarParkGasStationNozzleDTO;
import com.qd.common.panda.domain.entity.carpark.CarParkGasStationPriceDTO;
import com.qd.common.panda.domain.entity.carpark.CarParkInfoDTO;
import com.qd.common.panda.domain.entity.carpark.calculate.CalculateDTO;
import com.qd.common.panda.domain.entity.carpark.calculate.CalculatePriceDTO;
import com.qd.common.panda.domain.entity.carpark.calculate.CalculatePriceDetailDTO;
import com.qd.common.panda.domain.enums.GasStationCompanyNameEnum;
import com.qd.common.panda.domain.enums.PreferentialCategoryEnum;
import com.qd.common.sys.domain.login.LoginUser;
import com.qd.panda.gas.station.base.GasHttpService;
import com.qd.panda.gas.station.base.GasHttpServiceInitApplicationContextAware;
import com.qd.panda.gas.station.req.StationDetailReqDTO;
import com.qd.panda.gas.sync.EGasSyncService;
import com.qd.panda.mapper.park.CarParkGasStationMapper;
import com.qd.panda.model.CarParkGasStation;
import com.qd.panda.model.CarParkGasStationDiscountSet;
import com.qd.panda.service.discount.CarParkGasStationDiscountSetService;
import com.qd.panda.service.discount.ThirdPartyOfferService;
import com.qd.panda.service.stroke.BigDecimalUtil;
import com.qd.system.service.dict.MbUtil;
import com.qd.system.service.person.AuthTokenService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

import static java.util.stream.Collectors.toList;

/**
 * 加油站扩展信息
 *
 * @author sjk
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class CarParkGasStationService extends BaseService<CarParkGasStationMapper, CarParkGasStation> {

    private static final String PREFIX_ID = "panda_car_park_gas_station_pId_{0}";
    private static final String PREFIX_UNIQUE_PANDA_CAR = "panda_car_park_gas_station_gasStationCompanyName_{0}_stationId_{1}";

    private final CarParkGasStationPriceService carParkGasStationPriceService;

    private final CarParkGasStationDiscountSetService carParkGasStationDiscountSetService;
    private final CarParkGasStationNozzleService carParkGasStationNozzleService;
    private final RedisTemplateUtil<CarParkGasStation> redisTemplateUtil;
    private final RedisTemplateUtil<CalculatePriceDTO> calculatePriceRedisTemplateUtil;

    private final ThirdPartyOfferService thirdPartyOfferService;
    private final ObjectMapper objectMapper;
    private final AuthTokenService authTokenService;
    private static final List<Integer> DEFAULT_PRICE_LIST = Arrays.asList(100, 200, 300);

    /**
     * 保存
     *
     * @param dto 页面对象
     * @return 页面对象
     */
    @Transactional(rollbackFor = Exception.class)
    public CarParkGasStationDTO save(CarParkGasStationDTO dto) {
        checkUnique(dto);
        final CarParkGasStation model = dtoToModel(dto);
        try {
            if (super.save(model)) {
                return modelToDto(model);
            }
            throw new ApiException("添加失败");
        } finally {
            clearCache(model);
            model.freeData();
        }
    }

    /**
     * 修改
     *
     * @param dto 页面对象
     * @return 页面对象
     */
    @Transactional(rollbackFor = Exception.class)
    public CarParkGasStationDTO update(CarParkGasStationDTO dto) {
        checkUnique(dto);
        final CarParkGasStation historyModel = Optional.ofNullable(getById(dto.getPId())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        final CarParkGasStation model = dtoToModel(dto);
        try {
            if (super.updateById(model)) {
                return modelToDto(model);
            }
            throw new ApiException("更新失败");
        } finally {
            clearCache(model);
            clearCache(historyModel);
            historyModel.freeData();
            model.freeData();
        }
    }

    /**
     * 批量添加
     *
     * @param mList 数据库对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveBatch(List<CarParkGasStation> mList) {
        try {
            if (!super.saveBatch(mList)) {
                throw new ApiException("批量添加失败");
            }
        } finally {
            clearCaches(mList);
        }
    }

    /**
     * 批量更新
     *
     * @param mList 数据库对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBatchIds(List<CarParkGasStation> mList) {
        final List<String> ids = mList.stream().map(CarParkGasStation::getPId).collect(toList());
        final List<CarParkGasStation> historyModelList = checkIds(ids);
        try {
            if (!super.updateBatchById(mList)) {
                throw new ApiException("批量更新失败");
            }
        } finally {
            clearCaches(historyModelList);
            historyModelList.clear();
            ids.clear();
        }
    }

    /**
     * 删除，单个
     *
     * @param pId 主键
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeById(String pId) {
        final CarParkGasStation historyModel = Optional.ofNullable(getById(pId)).orElseThrow(() -> new ApiException("数据不存在,不能删除"));
        try {
            if (!super.removeById(pId)) {
                throw new ApiException("删除失败");
            }
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    /**
     * 批量删除
     *
     * @param ids 主键集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeBatchIds(List<String> ids) {
        final List<CarParkGasStation> historyModelList = checkIds(ids);
        try {
            if (!super.removeByIds(ids)) {
                throw new ApiException("批量删除失败");
            }
        } finally {
            clearCaches(historyModelList);
            historyModelList.clear();
        }
    }

    /**
     * 根据传入对象构建查询参数，判断是否存在
     *
     * @param dto 参数
     * @return 存在为true
     */
    @Transactional(readOnly = true)
    public Boolean isExists(CarParkGasStationDTO dto) {
        final QueryWrapper<CarParkGasStation> queryWrapper = createQueryWrapper(dto);
        final boolean exists = super.count(queryWrapper) > 0;
        queryWrapper.clear();
        return exists;
    }

    /**
     * 根据主键判断数据是否存在
     *
     * @param pId 主键
     * @return 存在为true
     */
    @Transactional(readOnly = true)
    public Boolean isExistsById(String pId) {
        boolean exists = false;
        if (StringUtils.hasLength(pId)) {
            final CarParkGasStation model = getById(pId);
            exists = (null != model);
            if (exists) {
                model.freeData();
            }
        }
        return exists;
    }

    /**
     * 根据主键获取数据
     *
     * @param pId 主键
     * @return 单条记录
     */
    @Transactional(readOnly = true)
    public CarParkGasStation getById(String pId) {
        final String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, pId);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> super.getById(pId), CarParkGasStation.class);
    }

    /**
     * 根据主键获取数据
     *
     * @param pId 主键
     * @return 单条记录，转换成页面对象
     */
    @Transactional(readOnly = true)
    public CarParkGasStationDTO getByIdDto(String pId) {
        return Optional.ofNullable(getById(pId)).map(this::modelToDto).orElse(null);
    }

    /**
     * 根据条件查询单条数据
     *
     * @param dto 查询参数
     * @return 单条记录
     */
    @Transactional(readOnly = true)
    public CarParkGasStation getOne(CarParkGasStationDTO dto) {
        final QueryWrapper<CarParkGasStation> queryWrapper = createQueryWrapper(dto);
        CarParkGasStation model = super.getOne(queryWrapper);
        queryWrapper.clear();
        return model;
    }

    /**
     * 根据条件查询单条数据
     *
     * @param dto 查询参数
     * @return 单条记录，转换成页面对象
     */
    @Transactional(readOnly = true)
    public CarParkGasStationDTO getOneDto(CarParkGasStationDTO dto) {
        return Optional.ofNullable(getOne(dto)).map(this::modelToDto).orElse(null);
    }

    /**
     * 根据条件查询列表数据
     *
     * @param dto 查询参数
     * @return 列表数据
     */
    @Transactional(readOnly = true)
    public List<CarParkGasStation> getList(CarParkGasStationDTO dto) {
        final QueryWrapper<CarParkGasStation> queryWrapper = createQueryWrapper(dto);
        final List<CarParkGasStation> list = super.list(queryWrapper);
        queryWrapper.clear();
        return list;
    }

    /**
     * 根据条件查询列表数据
     *
     * @param dto 查询参数
     * @return 列表数据，转换成页面对象
     */
    @Transactional(readOnly = true)
    public List<CarParkGasStationDTO> getListDto(CarParkGasStationDTO dto) {
        return modelToDtoList(getList(dto));
    }

    /**
     * 根据唯一性索引获得数据
     * param gasStationCompanyName
     * param stationId
     *
     * @return 单条数据
     */
    @Transactional(readOnly = true)
    public CarParkGasStation getUniqueByGasStationCompanyNameAndStationId(String gasStationCompanyName, String stationId) {
        final QueryWrapper<CarParkGasStation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("gas_station_company_name", gasStationCompanyName);
        queryWrapper.eq("station_id", stationId);
        final String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_UNIQUE_PANDA_CAR, gasStationCompanyName, stationId);
        final CarParkGasStation model = redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> super.getOne(queryWrapper, false), CarParkGasStation.class);
        queryWrapper.clear();
        return model;
    }

    /**
     * 验证唯一性索引
     *
     * @param dto 页面对象
     */
    @Transactional(readOnly = true)
    public void checkUnique(CarParkGasStationDTO dto) {
        CarParkGasStation model = getUniqueByGasStationCompanyNameAndStationId(dto.getGasStationCompanyName(), dto.getStationId());
        if (null != model) {
            checkUnique(dto, model);
        }
    }

    /**
     * 验证唯一性索引
     *
     * @param dto   页面对象
     * @param model 根据约束字段查询出来的数据库对象
     */
    private void checkUnique(CarParkGasStationDTO dto, CarParkGasStation model) {
        if (!StringUtils.hasLength(dto.getPId())) {
            throw new ApiException("数据已存在，请勿重复添加");
        }
        if (!dto.getPId().equals(model.getPId())) {
            throw new ApiException("数据已存在，请勿重复添加");
        }
    }

    /**
     * 清空缓存
     *
     * @param model 数据库对象
     */
    public void clearCache(CarParkGasStation model) {
        if (null == model) {
            return;
        }
        redisTemplateUtil.deleteByKey(RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getPId()));
        redisTemplateUtil.deleteByKey(RedisTemplateUtil.getRedisCacheKey(PREFIX_UNIQUE_PANDA_CAR, model.getGasStationCompanyName(), model.getStationId()));
    }

    /**
     * 批量清空缓存
     *
     * @param list 数据库对象
     */
    public void clearCaches(List<CarParkGasStation> list) {
        if (null == list || list.isEmpty()) {
            return;
        }
        List<String> ids = list.stream().map(model -> RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getPId())).collect(toList());
        if (!ids.isEmpty()) {
            redisTemplateUtil.deleteByKey(ids);
            ids.clear();
        }
        List<String> uniqueIds = list.stream().map(model -> RedisTemplateUtil.getRedisCacheKey(PREFIX_UNIQUE_PANDA_CAR, model.getGasStationCompanyName(), model.getStationId())).collect(toList());
        if (!uniqueIds.isEmpty()) {
            redisTemplateUtil.deleteByKey(uniqueIds);
            uniqueIds.clear();
        }
    }

    /**
     * 数据库对象转页面对象
     *
     * @param model 数据库对象
     * @return 页面对象
     */
    @Transactional(readOnly = true)
    public CarParkGasStationDTO modelToDto(CarParkGasStation model) {
        if (null == model) {
            return null;
        }
        final CarParkGasStationDTO dto = new CarParkGasStationDTO();
        dto.setPId(model.getPId());
        dto.setStationId(model.getStationId());
        dto.setCustomerDiscount(model.getCustomerDiscount());
        dto.setGasStationCompanyName(model.getGasStationCompanyName());
        dto.setNozzleNumbers(model.getNozzleNumbers());
        dto.setStationType(model.getStationType());
        if (null != model.getAdvert()) {
            try {
                dto.setAdvert(objectMapper.readValue(model.getAdvert(), JsonNode.class));
            } catch (JsonProcessingException ignored) {
            }
        }
        buildDisplay(dto);
        return dto;
    }

    /**
     * 页面对象转数据库对象
     *
     * @param dto 页面对象
     * @return 数据库对象
     */
    public CarParkGasStation dtoToModel(CarParkGasStationDTO dto) {
        if (null == dto) {
            return null;
        }
        final CarParkGasStation model = new CarParkGasStation();
        model.setPId(dto.getPId());
        model.setStationId(dto.getStationId());
        model.setCustomerDiscount(dto.getCustomerDiscount());
        model.setGasStationCompanyName(dto.getGasStationCompanyName());
        model.setNozzleNumbers(dto.getNozzleNumbers());
        model.setStationType(dto.getStationType());
        if (null != dto.getAdvert()) {
            model.setAdvert(dto.getAdvert().toString());
        }
        return model;
    }

    /**
     * 码表转换
     *
     * @param dto 页面对象
     */
    @Transactional(readOnly = true)
    public void buildDisplay(CarParkGasStationDTO dto) {
        dto.setGasStationCompanyNameDisplay(MbUtil.idToDisplay(dto.getGasStationCompanyName()));
        dto.setStationTypeDisplay(MbUtil.idToDisplay(dto.getStationType()));
        final List<CarParkGasStationNozzleDTO> stationNozzleList = carParkGasStationNozzleService.getGasStationNozzleDtoListByParkId(dto.getPId());
        if (!stationNozzleList.isEmpty()) {
            dto.setGasStationNozzleList(stationNozzleList);
        }
        final List<CarParkGasStationPriceDTO> priceList = carParkGasStationPriceService.getGasStationPriceDtoListByParkId(dto.getPId());
        if (!priceList.isEmpty()) {
            for (CarParkGasStationPriceDTO carParkGasStationPriceDTO : priceList) {
                final BigDecimal calculatePrice = getCalculatePrice(carParkGasStationPriceDTO, carParkGasStationPriceDTO.getPrice(), dto.getGasStationCompanyName());
                carParkGasStationPriceDTO.setCustomerPrice(calculatePrice);
                carParkGasStationPriceService.buildDisplay(carParkGasStationPriceDTO);
            }
            dto.setGasStationPriceList(priceList);
        }
    }

    /**
     * 数据库对象转页面对象
     *
     * @param list 数据库对象
     * @return 页面对象
     */
    public List<CarParkGasStationDTO> modelToDtoList(List<CarParkGasStation> list) {
        return Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(this::modelToDto).collect(toList());
    }

    /**
     * 页面对象转数据库对象
     *
     * @param list 页面对象
     * @return 数据库对象
     */
    public List<CarParkGasStation> dtoToModelList(List<CarParkGasStationDTO> list) {
        return Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(this::dtoToModel).collect(toList());
    }

    /**
     * 拼装查询参数，除了主键的其他字段会自动加入进来
     *
     * @param dto 查询参数，不为空的属性会被自动加入
     */
    public QueryWrapper<CarParkGasStation> createQueryWrapper(CarParkGasStationDTO dto) {
        return createQueryWrapper(dto, "");
    }

    /**
     * 拼装查询参数，除了主键的其他字段会自动加入进来
     *
     * @param dto        查询参数，不为空的属性会被自动加入
     * @param tableAlias 表别名
     */
    public QueryWrapper<CarParkGasStation> createQueryWrapper(CarParkGasStationDTO dto, String tableAlias) {
        final QueryWrapper<CarParkGasStation> queryWrapper = new QueryWrapper<>();
        if (null != dto) {
            if (StringUtils.hasLength(tableAlias) && tableAlias.charAt(tableAlias.length() - 1) != '.') {
                tableAlias += ".";
            }
            if (StringUtils.hasLength(dto.getStationId())) {
                queryWrapper.eq(tableAlias + "station_id", dto.getStationId());
            }
            if (StringUtils.hasLength(dto.getGasStationCompanyName())) {
                queryWrapper.eq(tableAlias + "gas_station_company_name", dto.getGasStationCompanyName());
            }
        }
        return queryWrapper;
    }

    /**
     * 批量检查主键在数据库中是否存在
     *
     * @param ids 主键集合
     * @return 主键查询出来的集合
     */
    public List<CarParkGasStation> checkIds(List<String> ids) {
        if (null == ids || ids.isEmpty()) {
            throw new ApiException("ids不能为空");
        }
        final List<CarParkGasStation> list = super.listByIds(ids);
        if (list.isEmpty()) {
            throw new ApiException("ids不存在" + Arrays.toString(ids.toArray()));
        }
        if (ids.size() == list.size()) {
            return list;
        }
        List<String> dbIds = list.stream().map(CarParkGasStation::getPId).collect(toList());
        final List<String> notExistsList = ids.stream().filter(id -> !dbIds.contains(id)).collect(toList());
        dbIds.clear();
        if (!notExistsList.isEmpty()) {
            throw new ApiException("ids不存在" + Arrays.toString(notExistsList.toArray()));
        }
        return list;
    }


    @Transactional(readOnly = true)
    public void build(CarParkInfoDTO carParkInfoDTO) {
        build(carParkInfoDTO, false, true, false);
    }

    @Transactional(readOnly = true)
    public void build(CarParkInfoDTO carParkInfoDTO, boolean calculate, boolean isAdvert, boolean isXyActivityNode) {
        final CarParkGasStationDTO carParkGasStationDTO = getByIdDto(carParkInfoDTO.getPId());
        if (null == carParkGasStationDTO) {
            return;
        }
        ObjectNode station = objectMapper.createObjectNode();
        station.put("discount", "加300省" + getDiscountAmount(carParkGasStationDTO.getPId(), BigDecimal.valueOf(300), carParkGasStationDTO.getGasStationCompanyName()).stripTrailingZeros().toPlainString());
        station.put("stationType", carParkGasStationDTO.getStationType());
        station.put("stationTypeDisplay", carParkGasStationDTO.getStationTypeDisplay());
        station.put("gasStationCompanyName", carParkGasStationDTO.getGasStationCompanyName());
        station.put("gasStationCompanyNameDisplay", carParkGasStationDTO.getGasStationCompanyNameDisplay());
//        station.put("gasStationCompanyName", carParkGasStationDTO.getGasStationCompanyName());
//        station.put("gasStationCompanyNameDisplay", carParkGasStationDTO.getGasStationCompanyNameDisplay());
        if (isAdvert) {
            station.set("advert", carParkGasStationDTO.getAdvert());
        }
        if (calculate) {
            station.put("nozzleNumbers", carParkGasStationDTO.getNozzleNumbers());
        }
        Map<Integer, XyActivity> xyActivityMap = null;
        if (isXyActivityNode) {
            xyActivityMap = queryXyActivity(carParkGasStationDTO);
        }

        final List<CarParkGasStationPriceDTO> gasStationPriceList = carParkGasStationDTO.getGasStationPriceList();
        if (null != gasStationPriceList && !gasStationPriceList.isEmpty()) {
            final ArrayNode priceArrayNode = objectMapper.createArrayNode();
            for (CarParkGasStationPriceDTO carParkGasStationPriceDTO : gasStationPriceList) {
                ObjectNode priceObjectNode = objectMapper.createObjectNode();
                priceObjectNode.put("octaneNumber", carParkGasStationPriceDTO.getOctaneNumber());
                priceObjectNode.put("price", carParkGasStationPriceDTO.getPrice().doubleValue());
                priceObjectNode.put("priceDisplay", carParkGasStationPriceDTO.getPriceDisplay());
                priceObjectNode.put("stationPrice", carParkGasStationPriceDTO.getStationPrice().doubleValue());
                priceObjectNode.put("stationPriceDisplay", carParkGasStationPriceDTO.getStationPriceDisplay());
                priceObjectNode.put("customerDiscount", carParkGasStationPriceDTO.getCustomerDiscount());
                priceObjectNode.put("customerPrice", carParkGasStationPriceDTO.getCustomerPrice().doubleValue());
                priceObjectNode.put("customerPriceDisplay", carParkGasStationPriceDTO.getCustomerPriceDisplay());
                if (isXyActivityNode) {
                    if (null != xyActivityMap && !xyActivityMap.isEmpty()) {
                        Optional.ofNullable(xyActivityMap.get(carParkGasStationPriceDTO.getOctaneNumber())).ifPresent(xyActivity -> priceObjectNode.putPOJO("xyActivity", xyActivity));
                    }
                }
                if (calculate) {
                    priceObjectNode.put("octaneNozzleNumbers", carParkGasStationPriceDTO.getNozzleNumbers());
                    final ArrayNode defaultPriceArrayNode = objectMapper.createArrayNode();
                    for (Integer calculatePrice : DEFAULT_PRICE_LIST) {
                        CalculatePriceDTO calculatePriceDTO = getAllDiscountAmount(carParkGasStationPriceDTO.getCustomerDiscount(), new BigDecimal(calculatePrice), carParkGasStationDTO.getGasStationCompanyName());
                        buildDisplay(calculatePriceDTO);
                        ObjectNode priceNode = objectMapper.createObjectNode();
                        priceNode.put("price", calculatePriceDTO.getPrice().doubleValue());
                        priceNode.put("priceDisplay", calculatePriceDTO.getPriceDisplay());
                        priceNode.put("calculatePrice", calculatePriceDTO.getCalculatePrice().doubleValue());
                        priceNode.put("calculatePriceDisplay", calculatePriceDTO.getCalculatePriceDisplay());
                        priceNode.put("discountAmount", calculatePriceDTO.getDiscountAmount().doubleValue());
                        priceNode.put("discountAmountDisplay", calculatePriceDTO.getDiscountAmountDisplay());
                        defaultPriceArrayNode.add(priceNode);
                        calculatePriceDTO.freeData();
                    }
                    priceObjectNode.set("priceList", defaultPriceArrayNode);
                }
                priceArrayNode.add(priceObjectNode);
            }
            station.set("gasStationPriceList", priceArrayNode);
        }
        carParkInfoDTO.setGasStation(station);
    }

    /**
     * 查询易加油的详细信息
     *
     * @param carParkGasStationDTO 查询参数
     * @return 每个油号对应的优惠信息
     */
    private Map<Integer, XyActivity> queryXyActivity(CarParkGasStationDTO carParkGasStationDTO) {
        if (carParkGasStationDTO.getGasStationCompanyName().equals(GasStationCompanyNameEnum.E_JIA_YOU.getCode())) {
            Map<Integer, XyActivity> xyActivityMap = new HashMap<>(5);
            //如果是易加油的加油站，需要拉去优惠信息
            LoginUser loginUser = authTokenService.getLoginUser(ServletUtil.getRequest());
            if (null != loginUser) {
                //有登陆信息的才拉去，因为优惠和人相关
                long start = System.currentTimeMillis();
                try {
                    final GasHttpService gasHttpService = GasHttpServiceInitApplicationContextAware.getGasHttpService(carParkGasStationDTO.getGasStationCompanyName());
                    if (null != gasHttpService) {
                        try {
                            StationDetailReqDTO stationDetailReqDTO = new StationDetailReqDTO()
                                    .setStationId(carParkGasStationDTO.getStationId())
                                    .setMobile(loginUser.getUserId());
                            JsonNode jsonNode = gasHttpService.getStationById(stationDetailReqDTO);
                            stationDetailReqDTO.freeData();
                            Optional.ofNullable(jsonNode.get("prices")).ifPresent(pricesNode -> pricesNode.forEach(priceNode -> Optional.ofNullable(priceNode.get("isXyActivity"))
                                    .ifPresent(isXyActivityNode -> {
                                        int isXyActivity = isXyActivityNode.intValue();
                                        if (isXyActivity == 0) {
                                            //表示有活动
                                            String oilCode = priceNode.get("oilCode").asText();
                                            Integer intOliCode = EGasSyncService.gasValueToId(oilCode);
                                            String iconInnerContent = priceNode.get("iconInnerContent").asText();
                                            String iconOuterContent = priceNode.get("iconOutererContent").asText();
                                            XyActivity xyActivity = new XyActivity();
                                            xyActivity.setIconInnerContent(iconInnerContent);
                                            xyActivity.setIconOuterContent(iconOuterContent);
                                            xyActivityMap.put(intOliCode, xyActivity);
//                                        } else {
//                                            //测试代码，正式删除,整个else都不需要
//                                            String oilCode = priceNode.get("oilCode").asText();
//                                            Integer intOliCode = EGasSyncService.gasValueToId(oilCode);
//                                            XyActivity xyActivity = new XyActivity();
//                                            if (intOliCode == 92) {
//                                                xyActivity.setIconInnerContent("满20升前5升享￥6.64/L");
//                                                xyActivity.setIconOuterContent("加油满20升，总价满160元，前5升优惠价为￥6.64/L，超出5升部分优惠价为￥7.92/L；总价不满160元，优惠价为￥7.45/L");
//                                            } else {
//                                                xyActivity.setIconInnerContent("满20升前5升享￥7.24/L");
//                                                xyActivity.setIconOuterContent("加油满20升，总价满170.6元，前5升优惠价为￥7.24/L，超出5升部分优惠价为￥8.53/L；总价不满170.6元，优惠价为￥7.98/L");
//                                            }
//                                            xyActivityMap.put(intOliCode, xyActivity);
                                        }
                                    })));
                        } finally {
                            long end = System.currentTimeMillis();
                            log.info("查询优惠活动,耗时: {}ms", (end - start));
                        }
                        return xyActivityMap;
                    }
                } catch (Exception ignored) {
                }
            }
        }
        return Collections.emptyMap();
    }

    public void buildAllDiscount(CalculatePriceDTO calculatePriceDTO) {
        final List<CalculatePriceDetailDTO> detailList = calculatePriceDTO.getDetailList();
        if (null == detailList || detailList.isEmpty()) {
            return;
        }
        Money discountAmount = new Money();
        for (CalculatePriceDetailDTO calculatePriceDetailDTO : detailList) {
            discountAmount = discountAmount.add(new Money(calculatePriceDetailDTO.getDiscountAmount()));
        }
        final Money calculatePrice = new Money(calculatePriceDTO.getPrice()).subtract(discountAmount);
        calculatePriceDTO.setCalculatePrice(calculatePrice.getAmount());
        calculatePriceDTO.setDiscountAmount(discountAmount.getAmount());

        buildDisplay(calculatePriceDTO);
    }

    void buildDisplay(CalculatePriceDTO calculatePriceDTO) {
        calculatePriceDTO.setPriceDisplay(calculatePriceDTO.getPrice().toPlainString());
        calculatePriceDTO.setCalculatePriceDisplay(calculatePriceDTO.getCalculatePrice().toPlainString());
        calculatePriceDTO.setDiscountAmountDisplay(calculatePriceDTO.getDiscountAmount().toPlainString());
        if (null == calculatePriceDTO.getServiceFee()) {
            calculatePriceDTO.setServiceFee(new BigDecimal("0"));
        }
        calculatePriceDTO.setServiceFeeDisplay(calculatePriceDTO.getServiceFee().toPlainString());
        if (null == calculatePriceDTO.getCouponAmount()) {
            calculatePriceDTO.setCouponAmount(new BigDecimal("0"));
        }
        calculatePriceDTO.setCouponAmountDisplay(calculatePriceDTO.getCouponAmount().toPlainString());
        if (null == calculatePriceDTO.getIntegralAmount()) {
            calculatePriceDTO.setIntegralAmount(new BigDecimal("0"));
        }
        calculatePriceDTO.setIntegralAmountDisplay(calculatePriceDTO.getIntegralAmount().toPlainString());
    }

    public void buildAutoHomeDiscount(BigDecimal originalPrice, CalculatePriceDTO calculatePrice) {
        Double customerDiscount = thirdPartyOfferService.getDiscount(PandaConstant.PLATFORM_AUTO_HOME);
        if (null == customerDiscount) {
            return;
        }
        if(log.isDebugEnabled()) {
            log.debug("汽车之家，折扣: {}", customerDiscount);
        }
        CalculateDTO calculateDTO = BigDecimalUtil.calculatePrice(originalPrice, customerDiscount);
        calculatePrice.addCalculatePriceDetailDTO(new CalculatePriceDetailDTO()
                .setCalculatePrice(calculateDTO.getCalculatePrice())
                .setPrice(calculateDTO.getPrice())
                .setDiscountAmount(calculateDTO.getDiscountAmount())
                .setCustomerDiscount(customerDiscount)
                .setPlatform(PandaConstant.PLATFORM_AUTO_HOME)
                .setServiceFee(new BigDecimal("0"))
                .setPreferentialCategory(PreferentialCategoryEnum.PREFERENTIAL_1.getCode())
        );
    }

    @Transactional(readOnly = true)
    public void buildGasDiscount(String parkId, BigDecimal originalPrice, CalculatePriceDTO calculatePrice) {
        final CarParkGasStation carParkGasStation = getById(parkId);
        if (null == carParkGasStation) {
            return;
        }
        buildGasDiscount(originalPrice, carParkGasStation.getGasStationCompanyName(), calculatePrice);
    }

    private void buildGasDiscount(BigDecimal originalPrice, String gasStationCompanyName, CalculatePriceDTO calculatePrice) {
        //获得加油站的折扣信息
        Double customerDiscount = getGasStationDiscountSet(gasStationCompanyName);
        if (null == customerDiscount) {
            return;
        }
        log.debug("加油站折扣: {}", customerDiscount);
        CalculateDTO calculateDTO = BigDecimalUtil.calculatePrice(originalPrice, customerDiscount);
        calculatePrice.setRefuelingAmount(calculateDTO.getCalculatePrice());
        calculatePrice.addCalculatePriceDetailDTO(new CalculatePriceDetailDTO()
                .setCalculatePrice(calculateDTO.getCalculatePrice())
                .setPrice(calculateDTO.getPrice())
                .setDiscountAmount(calculateDTO.getDiscountAmount())
                .setCustomerDiscount(customerDiscount)
                .setServiceFee(new BigDecimal("0"))
                .setPlatform(stationCompanyNameToPlatform(gasStationCompanyName))
                .setPreferentialCategory(PreferentialCategoryEnum.PREFERENTIAL_1.getCode())
        );
    }

    /**
     * 获得设置的加油站折扣信息
     *
     * @param gasStationCompanyName 加油站公司名称
     */
    public Double getGasStationDiscountSet(String gasStationCompanyName) {
        final CarParkGasStationDiscountSet carParkGasStationDiscountSet = carParkGasStationDiscountSetService.getById(gasStationCompanyName);
        if (null == carParkGasStationDiscountSet) {
            return null;
        }
        return carParkGasStationDiscountSet.getCustomerDiscount().doubleValue();
    }


    private Integer stationCompanyNameToPlatform(String stationCompanyName) {
        if (stationCompanyName.equals(GasStationCompanyNameEnum.EXTEND_SHELL.getCode())) {
            return PandaConstant.PLATFORM_EXTEND_SHELL;
        }
        if (stationCompanyName.equals(GasStationCompanyNameEnum.EXTEND_SHELL_HIGH.getCode())) {
            return PandaConstant.PLATFORM_EXTEND_SHELL;
        }
        if (stationCompanyName.equals(GasStationCompanyNameEnum.EXTEND_SHELL_OTHER.getCode())) {
            return PandaConstant.PLATFORM_EXTEND_SHELL;
        }
        if (stationCompanyName.equals(GasStationCompanyNameEnum.E_JIA_YOU.getCode())) {
            return PandaConstant.PLATFORM_E_GAS;
        }
        return -1;
    }

    /**
     * 获得优惠后的价格，针对加油站所属公司
     *
     * @param carParkGasStationPriceDTO 油号价格
     * @param originalPrice             原价
     * @param gasStationCompanyName     加油站对应的公司
     * @return 优惠价格
     */
    @Transactional(readOnly = true)
    public BigDecimal getCalculatePrice(CarParkGasStationPriceDTO carParkGasStationPriceDTO, BigDecimal originalPrice, String gasStationCompanyName) {
        CalculatePriceDTO calculatePrice = getAllDiscountAmount(carParkGasStationPriceDTO.getCustomerDiscount(), originalPrice, gasStationCompanyName);
        return null == calculatePrice ? new BigDecimal("0.00") : calculatePrice.getCalculatePrice();
    }

    /**
     * 获得优惠金额，针对加油站所属公司
     *
     * @param parkId                加油站ID
     * @param originalPrice         原价
     * @param gasStationCompanyName 加油站对应的公司
     * @return 优惠价格
     */
    @Transactional(readOnly = true)
    public BigDecimal getDiscountAmount(String parkId, BigDecimal originalPrice, String gasStationCompanyName) {
        Double customerDiscount = null;
        if (!gasStationCompanyName.equals(GasStationCompanyNameEnum.EXTEND_SHELL.getCode())) {
            CarParkGasStation carParkGasStation = getById(parkId);
            customerDiscount = carParkGasStation.getCustomerDiscount();
        }
        CalculatePriceDTO calculatePrice = getAllDiscountAmount(customerDiscount, originalPrice, gasStationCompanyName);
        return null == calculatePrice ? new BigDecimal("0.00") : calculatePrice.getDiscountAmount();
    }

    /**
     * 获得优惠金额，针对加油站所属公司
     *
     * @param customerDiscount      折扣
     * @param originalPrice         原价
     * @param gasStationCompanyName 加油站对应的公司
     * @return 优惠价格
     */
    @Transactional(readOnly = true)
    public CalculatePriceDTO getAllDiscountAmount(Double customerDiscount, BigDecimal originalPrice, String gasStationCompanyName) {
        //按折扣计算优惠金额
        if (gasStationCompanyName.equals(GasStationCompanyNameEnum.EXTEND_SHELL.getCode())) {
            //按公司计算优惠金额
            return getAllDiscountAmount(originalPrice, gasStationCompanyName);
        } else {
            //易加油、壳牌高速、壳牌民营
            return getEGasDiscountAmount(customerDiscount, originalPrice, gasStationCompanyName);
        }
    }


    /**
     * 获得易加油优惠金额
     *
     * @param customerDiscount      折扣
     * @param originalPrice         原始金额
     * @param gasStationCompanyName 加油站公司
     * @return 计算后的价格
     */
    @Transactional(readOnly = true)
    public CalculatePriceDTO getEGasDiscountAmount(Double customerDiscount, BigDecimal originalPrice, String gasStationCompanyName) {
        if (null == customerDiscount) {
            throw new ApiException("折扣不能为空");
        }
        String redisCacheKey = RedisTemplateUtil.getRedisCacheKey(CarParkGasStationDiscountSetService.PREFIX_CUSTOMER_DISCOUNT_AMOUNT, gasStationCompanyName, customerDiscount, originalPrice);
        return calculatePriceRedisTemplateUtil.get(new CacheKey().setKey(redisCacheKey).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> {
            CalculatePriceDTO calculatePriceDTO = new CalculatePriceDTO();
            calculatePriceDTO.setPrice(originalPrice);
            CalculateDTO calculateDTO = BigDecimalUtil.calculatePrice(originalPrice, customerDiscount);
            calculatePriceDTO.addCalculatePriceDetailDTO(new CalculatePriceDetailDTO()
                    .setCalculatePrice(calculateDTO.getCalculatePrice())
                    .setPrice(calculateDTO.getPrice())
                    .setDiscountAmount(calculateDTO.getDiscountAmount())
                    .setCustomerDiscount(customerDiscount)
                    .setPlatform(stationCompanyNameToPlatform(gasStationCompanyName)));
            calculatePriceDTO.setCalculatePrice(calculateDTO.getCalculatePrice());
            calculatePriceDTO.setDiscountAmount(calculateDTO.getDiscountAmount());
            return calculatePriceDTO;
        }, CalculatePriceDTO.class);

    }


    /**
     * 获得优惠金额
     *
     * @param originalPrice         原始金额
     * @param gasStationCompanyName 加油站公司
     * @return 计算后的价格
     */
    @Transactional(readOnly = true)
    public CalculatePriceDTO getAllDiscountAmount(BigDecimal originalPrice, String gasStationCompanyName) {
        String redisCacheKey = RedisTemplateUtil.getRedisCacheKey(CarParkGasStationDiscountSetService.PREFIX_ID_AMOUNT, gasStationCompanyName, originalPrice);
//        log.info("redisCacheKey： {}", redisCacheKey);
        return calculatePriceRedisTemplateUtil.get(new CacheKey().setKey(redisCacheKey).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> {
//            log.info("=======================");
            CalculatePriceDTO calculatePriceDTO = new CalculatePriceDTO();
            calculatePriceDTO.setPrice(originalPrice);
            calculatePriceDTO.setCalculatePrice(originalPrice);
            calculatePriceDTO.setDiscountAmount(new BigDecimal(0));
            //计算加油站优惠
            buildGasDiscount(originalPrice, gasStationCompanyName, calculatePriceDTO);
//            //计算汽车之家优惠
//            buildAutoHomeDiscount(originalPrice, calculatePriceDTO);
            //计算总优惠
            buildAllDiscount(calculatePriceDTO);
            return calculatePriceDTO;
        }, CalculatePriceDTO.class);
    }

    @Transactional(readOnly = true)
    public CarParkGasStation getByStationId(String stationId) {
        final QueryWrapper<CarParkGasStation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("station_id", stationId);
        final CarParkGasStation model = super.getOne(queryWrapper, false);
        queryWrapper.clear();
        return model;
    }

    @Data
    static class XyActivity {
        /**
         * 图标外文案（xy活动），为避免客诉该字段为必接字段
         */
        private String iconOuterContent;
        /**
         * 图标内文案（xy活动）
         */
        private String iconInnerContent;
    }
}